---
id: apply
slug: /versioned/apply
title: Applying Migrations
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

With the `atlas migrate apply` command, users can apply pending migrations to database(s). The typical flow for introducing
schema changes to databases is as follows: **Develop** ⇨ **Check (CI)** ⇨ **Push (CD)** ⇨ **Deploy**.

1. **Develop** - Generate a migration file with the desired database changes using the [`atlas migrate diff`](/versioned/diff) command.
2. **Check (CI)** - Use [`atlas migrate lint`](/versioned/lint) to validate migrations, ensuring they don't conflict with other team members' changes
   and align with best practices. Add Atlas to your CI pipeline in [GitHub Actions](/cloud/setup-ci) or [GitLab](/guides/ci-platforms/gitlab)
   to review migrations files before they get merged into the main branch.
3. **Push (Delivery)** - Use `atlas migrate push`, or set up a CI pipeline to push the latest migrations state to [Atlas Cloud](https://auth.atlasgo.cloud/signup).
   Alternatively, you can package the migrations directory into a custom Docker image and push it to an artifactory.
4. **Deploy** - Use `atlas migrate apply` to apply the pending migrations to your database(s).

### Flags and Arguments

By default, `atlas migrate apply` executes all pending migrations. However, you can pass an optional argument to limit the
number of migrations applied. For instance, `atlas migrate apply 2` will apply up to 2 pending migrations.

The following flags are required:

* `--url` the [URL](/concepts/url) to the database to apply migrations on.
* `--dir` the URL to the migration directory. It defaults to `file://migrations`.

:::info Reading remote directories
Users who have connected or pushed their migration directories to Atlas Cloud can read the migrations state directly from
there without needing to have them locally. For example, `atlas migrate apply --dir "atlas://app"` will apply the pending
migrations of the `app` project based on the most recent pushed state. To see it in action, run the following:

**Login** or signup:
```shell
atlas login
```

**Push** a local migration directory and name it `app`:
<Tabs>
<TabItem value="postgres" label="PostgreSQL">

```bash
atlas migrate push app \
  --dev-url "docker://postgres/15/dev?search_path=public"
```

</TabItem>
<TabItem value="mysql" label="MySQL">

```bash
atlas migrate push app \
  --dev-url "docker://mysql/8/dev"
```

</TabItem>
<TabItem value="maria" label="Maria">

```bash
atlas migrate push app \
  --dev-url "docker://mariadb/latest/dev"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```bash
atlas migrate push app \
  --dev-url "sqlite://dev?mode=memory"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```bash
atlas migrate push app \
  --dev-url "docker://sqlserver/2022-latest"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```bash
atlas migrate push app \
  --dev-url "docker://clickhouse/23.11"
```

</TabItem>
</Tabs>


**Deploy** to a local database the remote migration directory named `app`:
<Tabs>
<TabItem value="postgres" label="PostgreSQL">

```bash
atlas migrate apply \
  --dir "atlas://app" \
  --url "postgres://postgres:pass@:5432/example?search_path=public&sslmode=disable"
```

</TabItem>
<TabItem value="mysql" label="MySQL">

```bash
atlas migrate apply \
  --dir "atlas://app" \
  --url "mysql://root:pass@:3306/example"
```

</TabItem>
<TabItem value="maria" label="Maria">

```bash
atlas migrate apply \
  --dir "atlas://app" \
  --url "maria://root:pass@:3306/example"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```bash
atlas migrate apply \
  --dir "atlas://app" \
  --url "sqlite://example.db"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```bash
atlas migrate apply \
  --dir "atlas://app" \
  --url "sqlserver://sa:P@ssw0rd0995@:1433?database=master"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```bash
atlas migrate apply \
  --dir "atlas://app" \
  --url "clickhouse://root:pass@:9000/default"
```

</TabItem>
</Tabs>

**Deploy a specific tag** to a local database the remote migration directory named `app`:
<Tabs>
<TabItem value="postgres" label="PostgreSQL">

```bash
atlas migrate apply \
  --dir "atlas://app?tag=39e7e4e35fce7409bd26d25d8140061695d4ffd5" \
  --url "postgres://postgres:pass@:5432/example?search_path=public&sslmode=disable"
```

</TabItem>
<TabItem value="mysql" label="MySQL">

```bash
atlas migrate apply \
  --dir "atlas://app?tag=39e7e4e35fce7409bd26d25d8140061695d4ffd5" \
  --url "mysql://root:pass@:3306/example"
```

</TabItem>
<TabItem value="maria" label="Maria">

```bash
atlas migrate apply \
  --dir "atlas://app?tag=39e7e4e35fce7409bd26d25d8140061695d4ffd5" \
  --url "maria://root:pass@:3306/example"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```bash
atlas migrate apply \
  --dir "atlas://app?tag=39e7e4e35fce7409bd26d25d8140061695d4ffd5" \
  --url "sqlite://example.db"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```bash
atlas migrate apply \
  --dir "atlas://app?tag=39e7e4e35fce7409bd26d25d8140061695d4ffd5" \
  --url "sqlserver://sa:P@ssw0rd0995@:1433?database=master"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```bash
atlas migrate apply \
  --dir "atlas://app?tag=39e7e4e35fce7409bd26d25d8140061695d4ffd5" \
  --url "clickhouse://user:pass@:9000/default"
```

</TabItem>
</Tabs>
:::

### Schema Revision Information

Atlas saves information about the applied migrations on a table called `atlas_schema_revisions` in the connected
database schema (e.g. `mysql://user@host/my_schema` or `postgres://user@host/db?search_path=my_schema`). If the database
connection is not bound to a specific schema (e.g. `mysql://user@host/` or `postgres://user@host/db`), the table is
stored in its own schema called `atlas_schema_revisions`. This behavior can be changed by setting the schema manually:
+ `--revisions-schema my_schema` to store the data in `my_schema.atlas_schema_revisions`.

### Transaction Configuration

By default, Atlas creates one transaction per migration file and will roll back that transaction if a statement in the
wrapped migration fails to execute. Atlas supports three different transaction modes:
* `--tx-mode file` (default) will wrap each pending migration into its own transaction.
* `--tx-mode all` will wrap all pending migration files into one transaction.
* `--tx-mode none` will not create any transaction. If a statement fails, the execution will stop. However, Atlas is
smart enough to detect which statement fails and on another migration attempt will continue with the failed statement.
This means altering the migration file from the failed statements onwards is safe and recommended.

:::caution
Please be aware, that non DDL transactional databases like
MySQL (due to [implicit commits](https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html)) can not be safely rolled
back completely, and you might end up with a mismatched schema and revision table state. Atlas will handle those cases
in future releases. A good source of information can be found in the
[PostgreSQL wiki](https://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis).
:::

#### File level transaction mode

The `--atlas:txmode` directive can be used to override the transaction mode for a specific migration file:

```sql {1}
-- atlas:txmode none

CREATE INDEX CONCURRENTLY name_idx ON users (name);
```

### Execution Order

The `--exec-order` flag controls how Atlas computes and executes pending migration files to the database.
Atlas supports three different order execution modes:

- `linear` (default) - Atlas expects a linear history and fails if it encounters files that were added out of order.
  This option ensures files are executed in a consistent order, guaranteeing deterministic behavior. It can be enforced
  in CI using the `atlas migrate lint` command. Learn more about [non-linear changes](/lint/analyzers#non-linear-changes)
  in the documentation.
- `linear-skip` - This option is a softer version of `linear`, meaning that if Atlas encounters a new file that was not
   added in sequential order (its version is lower than the database version), it will be skipped.
- `non-linear` - This option directs Atlas to execute migration files that were added out of order. Note, although
  this option can be useful in local development, it is strongly discouraged in real production environments.
  Executing files out of order cannot guarantee deterministic behavior and may lead to failures (e.g., conflicted migrations).
  Rolling back to a specific version of the migration directory might be challenging, as the state of the database could differ
  from the state of the directory.

#### Handling Out-of-Order Errors {#non-linear-error}

:::caution Files were added out of order

You've encountered this issue because your database is at **version Z**, but there is a file(s) in your migration
directory pending to be applied with **version Y**, where **Y < Z**. This indicates it was added out of order, as its
version is lower than the current database version. Below are multiple options to resolve it depending on your environment:

:::

- **Local environment (development)**: Developers might encounter this issue if they have a migration file that was not
  yet pushed to the master branch (e.g., version Z), but upon pulling remote changes, new files with versions X and Y
  were added to the migration directory. In this scenario, there are two cases:
  - If the new (remote) changes **do not conflict** with the local changes, users can use the `--exec-order non-linear` flag
    to execute files that were added out of order (X and Y). In case of failure or unexpected behavior, the `atlas schema clean`
    command can be used to reset everything to a clean state.
  - If the new (remote) changes **conflict** with the local (_not yet pushed_) changes, the local database should be cleared
    using `atlas schema clean`, and the local changes should be adjusted to align with the pulled changes.

- **Real environment:** If you encountered this issue during deployment, it means that Atlas was not set up in your CI,
  which is why the issue was not detected beforehand. Let's go through the steps to fix the error and set up Atlas in
  your CI to prevent this issue from happening again:

  - Configure Atlas to run for every PR or a change in the master branch that affects the migration directory. Learn more on
  how to integrate it into your [GitHub Actions](/cloud/setup-ci) or [GitLab](/guides/ci-platforms/gitlab) CI pipelines.
  - Pull the latest changes from the master branch and run `atlas migrate rebase <versions>` to rebase the problematic
    files reported by Atlas (the _"out of order"_ ones). Then, create a PR.
  - At this stage, if Atlas CI is set up, it will verify that the migration directory is _replay-able_ and that the
    rebased migration file(s) can be executed without any issues (e.g., no conflicts with previous migrations).
  - Running `atlas migrate apply` (deployment) again should pass without this error.


### Existing Databases

#### Baseline migration

If you have an existing database project and want to switch over to Atlas Versioned Migrations, you need to provide
Atlas with a starting point. The first step is to create a migration file reflecting the current schema state. This can
be easily done:

<Tabs defaultValue="mysql">
<TabItem value="mysql" label="MySQL">

```shell
atlas migrate diff my_baseline \
  --dir "file://migrations" \
  --dev-url "docker://mysql/8/my_schema" \
  --to "mysql://root:pass@localhost:3306/my_schema"
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas migrate diff my_baseline \
  --dir "file://migrations" \
  --dev-url "docker://mariadb/latest/my_schema" \
  --to "maria://root:pass@localhost:3306/my_schema"
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas migrate diff my_baseline \
  --dir "file://migrations" \
  --dev-url "docker://postgres/15" \
  --to "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate diff my_baseline \
  --dir "file://migrations" \
  --dev-url "sqlite://file?mode=memory" \
  --to "sqlite://file.db"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```shell
atlas migrate diff my_baseline \
  --dir "file://migrations" \
  --dev-url "docker://sqlserver/2022-latest" \
  --to "sqlserver://sa:pass@localhost:1433?database=master"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```shell
atlas migrate diff my_baseline \
  --dir "file://migrations" \
  --dev-url "docker://clickhouse/23.11/default" \
  --to "clickhouse://user:pass@remote:9000/default"
```

</TabItem>
</Tabs>

Atlas will generate a "baseline" file from the database schema. For example:

```sql title="20220811074144_baseline.sql"
CREATE TABLE `users` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `age` bigint(20) NOT NULL,
    `name` varchar(255) COLLATE utf8mb4_bin NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `age` (`age`)
)
```

Regardless of whether you added additional migration files after the baseline, you need to specify the baseline version
during your first migration execution. Atlas will mark this version as already applied and proceed with the next version
after it. For example:

```shell
atlas migrate apply \
  --url "mysql://root:pass@localhost:3306/example" \
  --dir "file://migrations" \
  --baseline "20220811074144"
```

#### Allow Dirty

If your database contains resources but no revision information yet, Atlas will refuse to execute migration files. One
way to override that behavior is by using the `--baseline` flag. However, in cases where existing tables are not managed
by Atlas at all and should not be part of a baseline file, you can run the first migration execution with the
`--allow-dirty` flag to operate on a non-clean database.

```shell
atlas migrate apply \
  --url "mysql://root:pass@localhost:3306/example" \
  --dir "file://migrations" \
  --allow-dirty
```

### Dry Run

If you want to check what exactly Atlas would do when attempting a migration execution, you can provide the `--dry-run`
flag:
* `--dry-run` to not execute any SQL but print it on the screen.

### Down migrations

Migrations that "roll back" or reverse changes made to the database schema are called "down migrations". These are often
used during local development to undo the changes made by corresponding "up migrations". Atlas follows a linear
migration history model, in which all migration files are "roll-forward". However, it is still possible to clean or
revert schema changes made by specific migration files using the `schema clean` or `schema apply` commands. For example:

#### Reverting deleted migration files

1\. To undo the changes made by migration files that have already been deleted, you can use the [`schema apply`](../declarative/apply#migration-directory)
command to roll back the database state to the state defined by the migration directory:

<Tabs defaultValue="mysql">
<TabItem value="mysql" label="MySQL">

```shell
atlas schema apply \
  --url "mysql://root:pass@localhost:3306/example" \
  --to "file://migrations" \
  --dev-url "docker://mysql/8/example" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas schema apply \
  --url "maria://root:pass@localhost:3306/example" \
  --to "file://migrations" \
  --dev-url "docker://maria/latest/example" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas schema apply \
  --url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable" \
  --to "file://migrations" \
  --dev-url "docker://postgres/15" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas schema apply \
  --url "sqlite://file.db" \
  --to "file://migrations" \
  --dev-url "sqlite://file?mode=memory" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```shell
atlas schema apply \
  --url "sqlserver://sa:pass@remote:1433?database=master" \
  --to "file://migrations" \
  --dev-url "docker://sqlserver/2022-latest" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```shell
atlas schema apply \
  --url "clickhouse://user:pass@remote:9000/default" \
  --to "file://migrations" \
  --dev-url "clickhouse://localhost:9000/default" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
</Tabs>

2\. Remove the files/versions that were rolled back from the revision table:

<Tabs defaultValue="mysql">
<TabItem value="mysql" label="MySQL">

```shell
atlas migrate set \
  --url "mysql://root:pass@localhost:3306/example" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas migrate set \
  --url "maria://root:pass@localhost:3306/example" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas migrate set \
  --url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate set \
  --url "sqlite://file.db" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```shell
atlas migrate set \
  --url "sqlserver://sa:pass@remote:1433?database=master" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```shell
atlas migrate set \
  --url "clickhouse://user:pass@remote:9000/default" \
  --dir "file://migrations"
```

</TabItem>
</Tabs>

<details>
  <summary>Example output</summary>
  <div>

  ```text
  Current version is 20221207170547 (2 removed):

    - 20221225113035 (add_users)
    - 20221225113406 (add_blog_posts)

  ```

  </div>
</details>

3\. Verify the migration status by using the `atlas migrate status` command:

<Tabs defaultValue="mysql">
<TabItem value="mysql" label="MySQL">

```shell
atlas migrate status \
  --url "mysql://root:pass@localhost:3306/example" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas migrate status \
  --url "maria://root:pass@localhost:3306/example" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas migrate status \
  --url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate status \
  --url "sqlite://file.db" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```shell
atlas migrate status \
  --url "sqlserver://sa:pass@remote:1433?database=master" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```shell
atlas migrate status \
  --url "clickhouse://user:pass@remote:9000/default" \
  --dir "file://migrations"
```

</TabItem>
</Tabs>

<details>
  <summary>Example output</summary>
  <div>

  ```text
  Migration Status: OK
    -- Current Version: 20221207170547
    -- Next Version:    Already at latest version
    -- Executed Files:  25
    -- Pending Files:   0
  ```

  </div>
</details>

#### Reverting applied migration files

1\. To undo the changes made by migration files that are still present in the migration directory, you can use the
`version` parameter to specify that the database should be rolled back to the state defined in a specific version of
the migration directory. For example:

<Tabs defaultValue="mysql">
<TabItem value="mysql" label="MySQL">

```shell {3}
atlas schema apply \
  --url "mysql://root:pass@localhost:3306/example" \
  --to "file://migrations?version=20220925094437" \
  --dev-url "docker://mysql/8/example" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell {3}
atlas schema apply \
  --url "maria://root:pass@localhost:3306/example" \
  --to "file://migrations?version=20220925094437" \
  --dev-url "docker://maria/latest/example" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell {3}
atlas schema apply \
  --url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable" \
  --to "file://migrations?version=20220925094437" \
  --dev-url "docker://postgres/15" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell {3}
atlas schema apply \
  --url "sqlite://file.db" \
  --to "file://migrations?version=20220925094437" \
  --dev-url "sqlite://file?mode=memory" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```shell {3}
atlas schema apply \
  --url "sqlserver://sa:pass@remote:1433?database=master" \
  --to "file://migrations?version=20220925094437" \
  --dev-url "docker://sqlserver/2022-latest" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```shell {3}
atlas schema apply \
  --url "clickhouse://user:pass@remote:9000/default" \
  --to "file://migrations?version=20220925094437" \
  --dev-url "docker://clickhouse/23.11/default" \
  --exclude "atlas_schema_revisions"
```

</TabItem>
</Tabs>

```shell title="tree ." {6}
.
└── migrations
    ├── 20220925092817_initial.sql
    ├── 20220925094021_second.sql
    ├── 20220925094437_third.sql
    ├── 20220925094438_fourth.sql # changes made by this file are reverted.
    └── atlas.sum
```

2\. To remove the `20220925094438` version from the revision table, set the current version to the preceding one `20220925094437`:

<Tabs defaultValue="mysql">
<TabItem value="mysql" label="MySQL">

```shell
atlas migrate set 20220925094437 \
  --url "mysql://root:pass@localhost:3306/example" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas migrate set 20220925094437 \
  --url "maria://root:pass@localhost:3306/example" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas migrate set 20220925094437 \
  --url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate set 20220925094437 \
  --url "sqlite://file.db" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```shell
atlas migrate set 20220925094437 \
  --url "sqlserver://sa:pass@remote:1433?database=master" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```shell
atlas migrate set 20220925094437 \
  --url "clickhouse://user:pass@remote:9000/default" \
  --dir "file://migrations"
```

</TabItem>
</Tabs>

<details>
  <summary>Example output</summary>
  <div>

  ```text
  Current version is 20220925094437 (1 removed):

    - 20220925094438 (fourth)

  ```

  </div>
</details>

3\. Verify the migration status by using the `atlas migrate status` command:

<Tabs defaultValue="mysql">
<TabItem value="mysql" label="MySQL">

```shell
atlas migrate status \
  --url "mysql://root:pass@localhost:3306/example" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas migrate status \
  --url "maria://root:pass@localhost:3306/example" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas migrate status \
  --url "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate status \
  --url "sqlite://file.db" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```shell
atlas migrate status \
  --url "sqlserver://sa:pass@remote:1433?database=master" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```shell
atlas migrate status \
  --url "clickhouse://user:pass@remote:9000/default" \
  --dir "file://migrations"
```

</TabItem>
</Tabs>

<details>
  <summary>Example output</summary>
  <div>

  ```text
  Migration Status: PENDING
    -- Current Version: 20220925094437
    -- Next Version:    20220925094438
    -- Executed Files:  3
    -- Pending Files:   1
  ```

  </div>
</details>

#### Reverting all schema changes

In order to clean the entire schema, use the [`schema clean`](../cli-reference#atlas-schema-clean) command, and then use
[`migrate apply`](#flags) to replay the migration files. For example:

<Tabs defaultValue="mysql">
<TabItem value="mysql" label="MySQL">

```shell
atlas schema clean -u "mysql://root:pass@:3306/example"
atlas migrate apply -u "mysql://root:pass@:3306/example"
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas schema clean -u "maria://root:pass@localhost:3306/example"
atlas migrate apply -u "maria://root:pass@localhost:3306/example"
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas schema clean -u "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable"
atlas migrate apply -u "postgres://postgres:pass@localhost:5432/database?search_path=public&sslmode=disable"
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate status \
  --url "sqlite://file.db" \
  --dir "file://migrations"
```

</TabItem>
<TabItem value="sqlserver" label="SQL Server">

```shell
atlas schema clean -u "sqlserver://sa:pass@remote:1433?database=master"
atlas migrate apply -u "sqlserver://sa:pass@remote:1433?database=master"
```

</TabItem>
<TabItem value="clickhouse" label="ClickHouse">

```shell
atlas schema clean -u "clickhouse://user:pass@remote:9000/database"
atlas migrate apply -u "clickhouse://user:pass@remote:9000/database"
```

</TabItem>
</Tabs>

### Migration status

In addition to the `--dry-run` flag Atlas also provides the `atlas migrate status` command, that provides in-depth
information about the migration status of the connected database.


### Multi-Tenant environments

The Atlas configuration language provides built-in support for executing versioned workflows in multi-tenant
environments. Using the `for_each` meta-argument, users can define a single `env` block that is expanded to N instances,
one for each tenant:

```hcl title="atlas.hcl"
env "prod" {
  for_each = toset(var.tenants)
  url      = urlsetpath(var.url, each.value)
  migration {
    dir = "file://migrations"
  }
  format {
    migrate {
      apply = format(
        "{{ json . | json_merge %q }}",
        jsonencode({
          Tenant : each.value
        })
      )
    }
  }
}
```

[Read more](../atlas-schema/projects.mdx#multi-environment-example) about how to define versioned workflows using
project files in multi-tenant environments.

### Examples

First time apply with baseline on production environment:
```shell
atlas migrate apply \
  --env "production" \
  --baseline "20220811074144"
```

Execute 1 pending migration file, but don't run, but print SQL statements on screen:
```shell
atlas migrate apply 1 \
  --env "production" \
  --baseline "20220811074144" \
  --dry-run
```

Specify revision table schema and custom migration directory path:
```shell
atlas migrate apply \
  --url "mysql://root:pass@remote:3306/my_database" \
  --revisions-schema "atlas_migration_history" \
  --dir "file://custom/path/to/dir"
```

Ignore unclean database and run the first 3 migrations:
```shell
atlas migrate apply 3 \
  --url "mysql://root:pass@remote:3306/my_database" \
  --dir "file://custom/path/to/dir"
```

Run all pending migrations, but do not use a transaction:
```shell
atlas migrate apply \
  --url "mysql://root:pass@remote:3306/my_database" \
  --tx-mode "none"
```

Show information about the migration status of a deployment:
```shell
atlas migrate status \
  --url "mysql://root:pass@remote:3306/my_database" \
  --dir "file://custom/path/to/dir" \
  --revisions-schema "atlas_migration_history"
```

### Reference

[CLI Command Reference](/cli-reference#atlas-migrate-apply)
